import { message } from 'antd'
import axios, { AxiosError, AxiosInstance, AxiosResponse } from 'axios'

import store from '@/store'

import locale from '../locale'
import { MyAxiosRequestConfig, MyInternalAxiosRequestConfig, ResultData } from './requestType'
import { get, set } from './storage'

/**
 * 基础API
 */
const baseURL: string = import.meta.env.VITE_BASE_PULICAPI as string
console.log('QCR地址', import.meta.env.VITE_BASE_PULICAPI)
/**
 * 请求中的map
 */
const pendingMap = new Map()

/**
 * 生成每个请求唯一的键
 */
function getPendingKey(config: MyAxiosRequestConfig) {
  const { url, method, params = '', data = '' } = config
  return [url, method, JSON.stringify(params), JSON.stringify(data)].join('&')
}

/**
 * 储存每个请求唯一值, 也就是cancel()方法, 用于取消请求
 */
function addPending(config: MyAxiosRequestConfig) {
  const controller = new AbortController()
  const pendingKey = getPendingKey(config)
  config.signal = controller.signal
  pendingMap.set(pendingKey, controller)
}

/**
 * 删除重复的请求
 */
function removePending(config: MyAxiosRequestConfig) {
  const pendingKey = getPendingKey(config)
  if (pendingMap.has(pendingKey)) {
    const controller = pendingMap.get(pendingKey)
    pendingMap.delete(pendingKey)
    controller.abort()
  }
}

//创建一个service
const service: AxiosInstance = axios.create({
  baseURL,
  timeout: 10000, // request timeout
})

// 发起请求之前的拦截器
service.interceptors.request.use(
  (config: MyInternalAxiosRequestConfig) => {
    removePending(config)
    config.repeat_request_cancel && addPending(config)
    if (config.headers && typeof config.headers.set === 'function') {
      const token = store.getState().token ? store.getState().token : ''
      if (token) {
        config.headers.set('did', token)
      }
    }

    return config
  },
  (error: AxiosError) => Promise.reject(error)
)

const messageKey = 'updatable'
// 响应拦截器
service.interceptors.response.use(
  (response: AxiosResponse) => {
    removePending(response.config)
    const res = response.data
    if (response.status !== 200) {
      return Promise.reject(response)
    } else if (res.code * 1 === 0) {
      return response
    } else if (res.code * 1 === 7000) {
      // set('isCheck', false)
      set('isDeviceError', true)
      message.open({
        key: messageKey,
        type: 'error',
        content: locale[get('arco-lang')]['asyncData.device.error'],
        duration: 3,
      })
      return Promise.reject(response)
    } else {
      return Promise.reject(response)
    }
  },
  (error: AxiosError) => {
    error.config && removePending(error.config)
    return Promise.reject(error)
  }
)

//简单处理支持ts推导
const request = async <T>(config: MyAxiosRequestConfig): Promise<ResultData<T>> => {
  const restConfig = {
    repeat_request_cancel: true,
    ...config,
  }
  try {
    const { data } = await service.request<ResultData<T>>(restConfig)
    return data
  } catch (err) {
    throw err
  }
}
export default request
